/// @file ExchangeIO.h
/// @brief This file is the primary file for file exchange,provided for user use.
/// @details
/// @author JasonChen (jayhejiajia@126.com)
/// @date 2024-11-30
/// @version 0.1
/// 
/// @copyright Copyright (c) : Jiushao

#ifndef EXCHANGE_IO_H
#define EXCHANGE_IO_H

#include <memory>
#pragma once

#include "ExchangeObject.h"
#include "ExchangeParameter.h"
#include "ExchangeReporterTypes.h"
#include "pmi/ExchangeShapePMIInfos.h"

namespace  AMCAX::Exchange {
    class ExchangeDocumentInstance;

/// @brief set the log leve.
/// 
/// @param[in] none
/// @param[out] none
/// @return none
/// @retval none
/// @note none
/// @see none
void SetupLog() ;

class ExchangeIO ;

/// @brief Obtain the primary object for file exchange, which can be used for reading to or writing from file .
/// 
/// @param[in]  filePath: The file path of the file to be read or written.
/// @param[in]  isWrite: The filed is used to indicate whether the file is for reading or writing.
/// @param[out] ExchangeIO*:  The Object for reading or writing file.
/// @return If the file is unsupported ,it may return nullptr.
/// @retval none
/// @note For commercial file formats, the absolute path must be provided.
/// @see none
std::shared_ptr<ExchangeIO> Create(const std::string &filePath ,bool isWrite=false) ;

/// @brief Obtain the primary object for file exchange, which can be used for reading from  file .
/// 
/// @param[in]  inFileStream: The input file is passwd in a stream-based manner.
/// @param[in]  fileType: The type of the input file, which may or may not include "."
/// @param[out] ExchangeIO*:  The Object for reading or writing file.
/// @return If the file is unsupported ,it may return nullptr.
/// @retval none
/// @note For commercial file formats, the absolute path must be provided.
/// @see none
std::shared_ptr<ExchangeIO> Create(std::ifstream *inFileStream,const std::string &fileType) ;

/// @brief Obtain the primary object for file exchange, which can be used for writing tofile .
/// 
/// @param[in]  inFileStream: The input file is passed in a stream-based manner.
/// @param[in]  fileType: The type of the input file, which may or may not include "."
/// @param[out] ExchangeIO*:  The Object for reading or writing file.
/// @return If the file is unsupported ,it may return nullptr.
/// @retval none
/// @note For commercial file formats, the absolute path must be provided.
/// @see none
std::shared_ptr<ExchangeIO> Create(std::ofstream *outFileStream,const std::string &fileType) ;

/// @brief Reading & write file using the AMX file.
/// 
/// @param[in]  inFileStream: The input file is passed in a stream-based manner.
/// @param[in]  outFileStream: The out file is passed in a stream-based manner.
/// @param[out] ExchangeIO*:  The Object for reading or writing file.
/// @return If the file is unsupported ,it may return nullptr.
/// @retval none
/// @note For commercial file formats, the absolute path must be provided.
/// @see none
std::shared_ptr<ExchangeIO>  CreateAmx(std::shared_ptr<std::fstream> inFileStream,std::shared_ptr<std::fstream> outFileStream) ;

/// @ingroup The main module for file exchange.
/// @brief Primaryily used for reading and writing files, the file can be passwd either by file name or through a stream.
/// 
class ExchangeIO
{
public:
    virtual ~ExchangeIO() = default ;
    /// @brief Read file content.
    /// 
    /// @param[in] NONE
    /// @param[out] NONE
    /// @return NONE
    /// @retval NONE
    /// @note NONE
    /// @see NONE
    virtual void Read() = 0 ;
    
    /// @brief  Generate files in other formats based on the contents of the file.
    /// 
    /// @param[in] exchangeShapes:  The data information of the model may come from other files or be manually constructed.
    /// @param[out] NONE
    /// @return NONE
    /// @retval NONE
    /// @note NONE
    /// @see NONE
    virtual void Write(const std::vector<std::shared_ptr<ExchangeObject>>& exchangeShapes, const std::shared_ptr<ExchangeDocumentInstance> &exchangeDocumentInstance) = 0 ;
    
    /// @brief Retrieve the information of the model.
    /// 
    /// @param[in] NONE
    /// @param[out] std::vector<std::shared_ptr<ExchangeObject>> &:  The data information of the model.
    /// @return Primaryly the information of the model , which may be empty in this case.
    /// @retval NONE
    /// @note NONE
    /// @see NONE
    virtual const std::vector<std::shared_ptr<ExchangeObject>> & GetShapes() = 0;

    virtual const std::shared_ptr<ExchangeDocumentInstance> & GetDocumentRootInstance() = 0;


    /// @brief Set some additional parameters. such as precision control when coverting to obj or stdl
    /// 
    /// @param[in] outputParameter:  Additional paramater information
    /// @param[out] NONE
    /// @return NONE
    /// @retval NONE
    /// @note NONE
    /// @see NONE
    virtual void SetExchangeParameter(ExchangeParameter *outputParameter) = 0 ;

    
    /// @brief Convert the file from one format to another.
    ///
    /// @param[in] inFilePath: The input file path.
    /// @param[in] outFilePath: The output file path.
    /// @return NONE
    /// @retval NONE
    /// @note NONE
    /// @see NONE
    static void Convert(const std::string &inFilePath, const std::string &outFilePath) ;

    /// @brief Retrieve the metadata of the file.
    ///
    /// @param[in] inFilePath: The input file path.
    /// @param[in] outFilePath: The output metadata file path.
    /// @param[in] inputParameter: The input exchange parameter.
    /// @return The result metadata.
    static std::shared_ptr<ExchangeParameter> GetMetaData(const std::string &inFilePath, const std::string &outFilePath, const std::shared_ptr<ExchangeParameter> &inputParameter = nullptr);

    /// @brief Get document information
    /// @param inFilePath input file path.
    /// @param outJson output document information in json format
    static void GetDocumentInfo(const std::string &inFilePath, std::string &outJson);

    /// @brief Get document properties
    /// @param inFilePath input file path.
    /// @param outJson output document properties in json format
    /// @param includingChildren return properties of children recursively
    static void GetProperties(const std::string &inFilePath, std::string &outJson, bool includingChildren = false);
    static void SetReporter(ExchangeReporterType operationType) ;
    
    static std::unordered_map<std::string,Core::PMI::ExchangeShapePMIInfos> GetPMI(const std::string &filePath) ;
} ;

} ;


#endif // EXCHANGE_IO_H